package common.entities.persistent;

import common.entities.abst.AbstPersistentEntity;

/**
 * @author Yoyo
 *
 */
public class Movie extends AbstPersistentEntity {
	public static int titleMinLength = 1;
	public static int titleMaxLength = 70;
	
	public static int releaseYearMinValue = 1960;
	public static int releaseYearMaxValue = 2012;
	
	public static float rankMinValue = 0.0F;
	public static float rankMaxValue = 10.0F;
	
	public static int votesMinValue = 0;
	public static int votesMaxValue = Integer.MAX_VALUE-1;
	
	private String title;
	private int releaseYear;
	private float rank;
	private int votes;
	
	/**
	 * This constructor will be used for entities that are fetched from the DB
	 * 
	 * @param id
	 * @param title
	 * @param releaseYear
	 * @param rank
	 * @param votes
	 */
	public Movie(int id, String title, int releaseYear, float rank, int votes) {
		super(id);
		
		this.title = fixEscapeCharacters(title);
		this.releaseYear = releaseYear;
		this.rank = rank;
		this.votes = votes;
	}
	
	public Movie(int id, String title, int releaseYear, float rank) {
		super(id);
		
		this.title = fixEscapeCharacters(title);
		this.releaseYear = releaseYear;
		this.rank = rank;
	}
	
	/**
	 * This constructor will be used for new entities (i.e still weren't saved into DB)
	 * 
	 * @param title
	 * @param releaseYear
	 * @param rank
	 * @param votes
	 */
	public Movie(String title, int releaseYear, float rank, int votes) {
		super();
		
		this.title = fixEscapeCharacters(title);
		this.releaseYear = releaseYear;
		this.rank = rank;
		this.votes = votes;
	}

	public Movie() {
		this(null, releaseYearMinValue, rankMinValue, votesMinValue);
	}
	

	/**
	 * @param title the title to set
	 */
	public static void setReleaseYearMaxValue(int releaseYearMaxValue) {
		Movie.releaseYearMaxValue = releaseYearMaxValue;
	}
	
	
	/**
	 * @return the title
	 */
	public String getTitle() {
		return fixEscapeCharactersReverse(title);
	}
	
	public String escapedGetTitle() {
		return title;
	}

	/**
	 * @return the releaseYear
	 */
	public int getReleaseYear() {
		return releaseYear;
	}


	/**
	 * @return the rank
	 */
	public float getRank() {
		return rank;
	}

	/**
	 * @return the votes
	 */
	public int getVotes() {
		return votes;
	}
	
	/**
	 * @param title the title to set
	 */
	public void setTitle(String title) {
		this.title = fixEscapeCharacters(title);
	}

	/**
	 * @param releaseYear the releaseYear to set
	 */
	public void setReleaseYear(int releaseYear) {
		this.releaseYear = releaseYear;
	}

	public void setReleaseYear(String releaseYear) {
		setReleaseYear(Integer.parseInt(releaseYear));
	}
	
	/**
	 * @param rank the rank to set
	 */
	public void setRank(float rank) {
		this.rank = rank;
	}
	
	public void setRank(String rank) {
		setRank(Float.parseFloat(rank));
	}

	/**
	 * @param votes the votes to set
	 */
	public void setVotes(int votes) {
		this.votes = votes;
	}
	
	public void setVotes(String votes) {
		setVotes(Integer.parseInt(votes));
	}
	
	public void setValues(String title, String releaseYear) {
		this.title = title;
		this.setReleaseYear(releaseYear);
	}
	
	public void setValues(String title, String releaseYear, String rank, String votes) {
		this.title = title;
		this.setReleaseYear(releaseYear);
		this.setRank(rank);
		this.setVotes(votes);
	}
	
	/**
	 * Is used to check the restrictions of the movie. 
	 * @param movie 
	 * @return true if it's fields violate the restrictions, and false otherwise
	 */
	public boolean isViolateRestrictions(int releaseYearMinValue, int releaseYearMaxValue) {
		if(this.title == null)
			return true;
		else if(this.getTitle().length() <= Movie.titleMinLength ||
				this.getTitle().length() >= Movie.titleMaxLength)
			return true;
		else if(this.getReleaseYear() < releaseYearMinValue ||
				this.getReleaseYear() > releaseYearMaxValue)
			return true;
		
		return false;
	}
	
	/**
	 * Is used to validate the title according to the DB constraints
	 * 
	 * @param title
	 * @throws IllegalArgumentException
	 */
	public static void validateTitle(String title) throws IllegalArgumentException{
		if(title == null)
			throw new IllegalArgumentException("Title cannot be null");
		else if(title.length() < Movie.titleMinLength)
			throw new IllegalArgumentException(String.format("Title cannot have less than %s characters", Movie.titleMinLength));
		else if(title.length() > Movie.titleMaxLength)
			throw new IllegalArgumentException(String.format("Title cannot have more than %s characters", Movie.titleMaxLength));
	}
	
	/**
	 * Is used to validate the rank according to the DB constraints
	 * 
	 * @param rank
	 * @throws IllegalArgumentException
	 */
	public static void validateRank(float rank) throws IllegalArgumentException{
		if(rank < Movie.rankMinValue)
			throw new IllegalArgumentException(String.format("Rank must have value greater than %s", Movie.rankMinValue));
		else if(rank > Movie.rankMaxValue)
			throw new IllegalArgumentException(String.format("Rank must have value smaller than %s", Movie.rankMinValue));
	}
	
	/**
	 * Is used to validate the release year according to the DB constraints
	 * 
	 * @param releaseYear
	 * @throws IllegalArgumentException
	 */
//	public static void validateReleaseYear(int releaseYear) throws IllegalArgumentException{
//		if(releaseYear < Movie.releaseYearMinValue)
//			throw new IllegalArgumentException(String.format("Release year must have value greater than %s", Movie.releaseYearMinValue));
//		else if(releaseYear > Movie.releaseYearMaxValue)
//			throw new IllegalArgumentException(String.format("Release year must have value smaller than %s", Movie.releaseYearMaxValue));
//	}

	
	@Override
	public String toString() {
		return "Movie: " + this.getTitle() + "  (" + this.getReleaseYear() + ")  " +
				"(" + this.getRank() + ", " + this.getVotes() + ")";
	}

	@Override
	public boolean equals(Object obj) {
		Movie cmpMovie = (Movie) obj;
		
		return ( (this.getTitle().equals(cmpMovie.getTitle())) && 
				 (this.getReleaseYear() == cmpMovie.getReleaseYear()) );
	}

	
	
}
